package i18n

import (
	"bytes"
	"encoding/json"
	"os"
	"path/filepath"
	"strings"
	"text/template"
)

var DefaultLocale = "en-US"

type Locale map[string]string
type Locales map[string]Locale

type I18n struct {
	LocalesDir string
	Locale     string
	Locales    Locales
}

func NewI18n(localesDir string) *I18n {
	locales, err := Load(localesDir)
	i18n := &I18n{
		LocalesDir: localesDir,
		Locale:     DefaultLocale,
	}
	if err == nil {
		i18n.Locales = locales
	}
	return i18n
}

func (i *I18n) T(key string) string {
	return i.TWithData(key, nil)
}

func (i *I18n) TWithData(key string, data any) string {
	if msgs, ok := i.Locales[i.Locale]; ok {
		if msg, ok := msgs[key]; ok {
			if msg != "" {
				return i.renderTemplate(msg, data)
			} else {
				return i.renderTemplate(key, data)
			}
		}
	}

	return i.renderTemplate(key, data)
}

func (i *I18n) renderTemplate(templateStr string, data any) string {
	if data == nil {
		return templateStr
	}

	// 使用 Go 标准库的 text/template 进行模板渲染
	tmpl, err := template.New("i18n").Parse(templateStr)
	if err != nil {
		// 如果模板解析失败，返回原始字符串
		return templateStr
	}

	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, data); err != nil {
		// 如果模板执行失败，返回原始字符串
		return templateStr
	}

	return buf.String()
}

func Load(localesDir string) (Locales, error) {
	entries, err := os.ReadDir(localesDir)
	if err != nil {
		return nil, err
	}

	locales := make(Locales)
	for _, entry := range entries {
		if entry.IsDir() {
			continue
		}

		if strings.HasSuffix(entry.Name(), ".json") {
			locale := strings.TrimSuffix(entry.Name(), ".json")
			filePath := filepath.Join(localesDir, locale+".json")
			data, err := os.ReadFile(filePath)
			if err != nil {
				return nil, err
			}

			var messages Locale
			if err := json.Unmarshal(data, &messages); err != nil {
				return nil, err
			}

			locales[locale] = messages
		}
	}

	return locales, nil
}
